home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / sendmail.8.8.4.tar.gz / sendmail.8.8.4.tar / sendmail-8.8.4 / smrsh / smrsh.c < prev   
C/C++ Source or Header  |  1996-09-25  |  6KB  |  234 lines

  1. /*
  2.  * Copyright (c) 1993 Eric P. Allman
  3.  * Copyright (c) 1993
  4.  *    The Regents of the University of California.  All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *    This product includes software developed by the University of
  17.  *    California, Berkeley and its contributors.
  18.  * 4. Neither the name of the University nor the names of its contributors
  19.  *    may be used to endorse or promote products derived from this software
  20.  *    without specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  */
  34.  
  35. #ifndef lint
  36. static char sccsid[] = "@(#)smrsh.c    8.4 (Berkeley) 11/11/95";
  37. #endif /* not lint */
  38.  
  39. /*
  40. **  SMRSH -- sendmail restricted shell
  41. **
  42. **    This is a patch to get around the prog mailer bugs in most
  43. **    versions of sendmail.
  44. **
  45. **    Use this in place of /bin/sh in the "prog" mailer definition
  46. **    in your sendmail.cf file.  You then create CMDDIR (owned by
  47. **    root, mode 755) and put links to any programs you want
  48. **    available to prog mailers in that directory.  This should
  49. **    include things like "vacation" and "procmail", but not "sed"
  50. **    or "sh".
  51. **
  52. **    Leading pathnames are stripped from program names so that
  53. **    existing .forward files that reference things like
  54. **    "/usr/ucb/vacation" will continue to work.
  55. **
  56. **    The following characters are completely illegal:
  57. **        <  >  |  ^  ;  &  $  `  (  ) \n \r
  58. **    This is more restrictive than strictly necessary.
  59. **
  60. **    To use this, edit /etc/sendmail.cf, search for ^Mprog, and
  61. **    change P=/bin/sh to P=/usr/local/etc/smrsh, where this compiled
  62. **    binary is installed /usr/local/etc/smrsh.
  63. **
  64. **    This can be used on any version of sendmail.
  65. **
  66. **    In loving memory of RTM.  11/02/93.
  67. */
  68.  
  69. #include <unistd.h>
  70. #include <stdio.h>
  71. #include <sys/file.h>
  72. #include <string.h>
  73. #include <ctype.h>
  74. #ifdef EX_OK
  75. # undef EX_OK
  76. #endif
  77. #include <sysexits.h>
  78. #include <syslog.h>
  79.  
  80. /* directory in which all commands must reside */
  81. #ifndef CMDDIR
  82. # define CMDDIR        "/usr/adm/sm.bin"
  83. #endif
  84.  
  85. /* characters disallowed in the shell "-c" argument */
  86. #define SPECIALS    "<|>^();&`$\r\n"
  87.  
  88. /* default search path */
  89. #ifndef PATH
  90. # define PATH        "/bin:/usr/bin:/usr/ucb"
  91. #endif
  92.  
  93. main(argc, argv)
  94.     int argc;
  95.     char **argv;
  96. {
  97.     register char *p;
  98.     register char *q;
  99.     register char *cmd;
  100.     int i;
  101.     char *newenv[2];
  102.     char cmdbuf[1000];
  103.     char pathbuf[1000];
  104.  
  105. #ifndef LOG_MAIL
  106.     openlog("smrsh", 0);
  107. #else
  108.     openlog("smrsh", LOG_ODELAY|LOG_CONS, LOG_MAIL);
  109. #endif
  110.  
  111.     strcpy(pathbuf, "PATH=");
  112.     strcat(pathbuf, PATH);
  113.     newenv[0] = pathbuf;
  114.     newenv[1] = NULL;
  115.  
  116.     /*
  117.     **  Do basic argv usage checking
  118.     */
  119.  
  120.     if (argc != 3 || strcmp(argv[1], "-c") != 0)
  121.     {
  122.         fprintf(stderr, "Usage: %s -c command\n", argv[0]);
  123.         syslog(LOG_ERR, "usage");
  124.         exit(EX_USAGE);
  125.     }
  126.  
  127.     /*
  128.     **  Disallow special shell syntax.  This is overly restrictive,
  129.     **  but it should shut down all attacks.
  130.     **  Be sure to include 8-bit versions, since many shells strip
  131.     **  the address to 7 bits before checking.
  132.     */
  133.  
  134.     strcpy(cmdbuf, SPECIALS);
  135.     for (p = cmdbuf; *p != '\0'; p++)
  136.         *p |= '\200';
  137.     strcat(cmdbuf, SPECIALS);
  138.     p = strpbrk(argv[2], cmdbuf);
  139.     if (p != NULL)
  140.     {
  141.         fprintf(stderr, "%s: cannot use %c in command\n",
  142.             argv[0], *p);
  143.         syslog(LOG_CRIT, "uid %d: attempt to use %c in command: %s",
  144.             getuid(), *p, argv[2]);
  145.         exit(EX_UNAVAILABLE);
  146.     }
  147.  
  148.     /*
  149.     **  Do a quick sanity check on command line length.
  150.     */
  151.  
  152.     i = strlen(argv[2]);
  153.     if (i > (sizeof cmdbuf - sizeof CMDDIR - 2))
  154.     {
  155.         fprintf(stderr, "%s: command too long: %s\n", argv[0], argv[2]);
  156.         syslog(LOG_WARNING, "command too long: %.40s", argv[2]);
  157.         exit(EX_UNAVAILABLE);
  158.     }
  159.  
  160.     /*
  161.     **  Strip off a leading pathname on the command name.  For
  162.     **  example, change /usr/ucb/vacation to vacation.
  163.     */
  164.  
  165.     /* strip leading spaces */
  166.     for (q = argv[2]; *q != '\0' && isascii(*q) && isspace(*q); )
  167.         q++;
  168.  
  169.     /* find the end of the command name */
  170.     p = strpbrk(q, " \t");
  171.     if (p == NULL)
  172.         cmd = &q[strlen(q)];
  173.     else
  174.     {
  175.         *p = '\0';
  176.         cmd = p;
  177.     }
  178.  
  179.     /* search backwards for last / (allow for 0200 bit) */
  180.     while (cmd > q)
  181.     {
  182.         if ((*--cmd & 0177) == '/')
  183.         {
  184.             cmd++;
  185.             break;
  186.         }
  187.     }
  188.  
  189.     /* cmd now points at final component of path name */
  190.  
  191.     /*
  192.     **  Check to see if the command name is legal.
  193.     */
  194.  
  195.     (void) strcpy(cmdbuf, CMDDIR);
  196.     (void) strcat(cmdbuf, "/");
  197.     (void) strcat(cmdbuf, cmd);
  198. #ifdef DEBUG
  199.     printf("Trying %s\n", cmdbuf);
  200. #endif
  201.     if (access(cmdbuf, X_OK) < 0)
  202.     {
  203.         /* oops....  crack attack possiblity */
  204.         fprintf(stderr, "%s: %s not available for sendmail programs\n",
  205.             argv[0], cmd);
  206.         if (p != NULL)
  207.             *p = ' ';
  208.         syslog(LOG_CRIT, "uid %d: attempt to use %s", getuid(), cmd);
  209.         exit(EX_UNAVAILABLE);
  210.     }
  211.     if (p != NULL)
  212.         *p = ' ';
  213.  
  214.     /*
  215.     **  Create the actual shell input.
  216.     */
  217.  
  218.     strcpy(cmdbuf, CMDDIR);
  219.     strcat(cmdbuf, "/");
  220.     strcat(cmdbuf, cmd);
  221.  
  222.     /*
  223.     **  Now invoke the shell
  224.     */
  225.  
  226. #ifdef DEBUG
  227.     printf("%s\n", cmdbuf);
  228. #endif
  229.     execle("/bin/sh", "/bin/sh", "-c", cmdbuf, NULL, newenv);
  230.     syslog(LOG_CRIT, "Cannot exec /bin/sh: %m");
  231.     perror("/bin/sh");
  232.     exit(EX_OSFILE);
  233. }
  234.